﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using AgileShare.Framework.Core;

namespace AgileShare.Framework.CamlQueries
{
	/// <summary>
	/// 
	/// </summary>
	public static class CamlQueryHelper
	{
		// SPList Overloads

		/// <summary>
		/// Gets the items.
		/// </summary>
		/// <param name="camlQueryBuilder">The caml query builder.</param>
		/// <param name="list">The list.</param>
		/// <param name="rowLimit">The row limit.</param>
		/// <returns></returns>
		public static SPListItemCollection GetItems(CamlQueryBuilder camlQueryBuilder, SPList list, uint? rowLimit = null)
		{
			CamlQuery camlQuery = new CamlQuery(camlQueryBuilder, rowLimit);
			var items = list.GetItems(camlQuery);
			return items;
		}

		/// <summary>
		/// Gets the items.
		/// </summary>
		/// <param name="fieldId">The field id.</param>
		/// <param name="comparisonOperator">The comparison operator.</param>
		/// <param name="value">The value.</param>
		/// <param name="valueType">Type of the value.</param>
		/// <param name="list">The list.</param>
		/// <param name="rowLimit">The row limit.</param>
		/// <param name="viewFieldIds">The view field ids.</param>
		/// <returns></returns>
		public static SPListItemCollection GetItems(Guid fieldId, ComparisonOperator comparisonOperator, object value, CamlValueType valueType, SPList list, uint? rowLimit = null, params Guid[] viewFieldIds)
		{
			CamlQueryBuilder cqb = new CamlQueryBuilder(fieldId, comparisonOperator, value, valueType, viewFieldIds);
			var items = GetItems(cqb, list, rowLimit);
			return items;
		}

		/// <summary>
		/// Gets the items.
		/// </summary>
		/// <param name="fieldName">Name of the field.</param>
		/// <param name="comparisonOperator">The comparison operator.</param>
		/// <param name="value">The value.</param>
		/// <param name="valueType">Type of the value.</param>
		/// <param name="list">The list.</param>
		/// <param name="rowLimit">The row limit.</param>
		/// <param name="viewFieldNames">The view field names.</param>
		/// <returns></returns>
		public static SPListItemCollection GetItems(string fieldName, ComparisonOperator comparisonOperator, object value, CamlValueType valueType, SPList list, uint? rowLimit = null, params string[] viewFieldNames)
		{
			CamlQueryBuilder cqb = new CamlQueryBuilder(fieldName, comparisonOperator, value, valueType, viewFieldNames);
			var items = GetItems(cqb, list, rowLimit);
			return items;
		}

		/// <summary>
		/// Gets the items.
		/// </summary>
		/// <param name="fieldId">The field id.</param>
		/// <param name="comparisonOperator">The comparison operator.</param>
		/// <param name="value">The value.</param>
		/// <param name="valueType">Type of the value.</param>
		/// <param name="orderByFieldId">The order by field id.</param>
		/// <param name="orderByDirection">The order by direction.</param>
		/// <param name="list">The list.</param>
		/// <param name="rowLimit">The row limit.</param>
		/// <param name="viewFieldIds">The view field ids.</param>
		/// <returns></returns>
		public static SPListItemCollection GetItems(Guid fieldId, ComparisonOperator comparisonOperator, object value, CamlValueType valueType, Guid orderByFieldId, OrderByDirection orderByDirection, SPList list, uint? rowLimit = null, params Guid[] viewFieldIds)
		{
			CamlQueryBuilder cqb = new CamlQueryBuilder(fieldId, comparisonOperator, value, valueType, orderByFieldId, orderByDirection, viewFieldIds);
			var items = GetItems(cqb, list, rowLimit);
			return items;
		}

		/// <summary>
		/// Gets the items.
		/// </summary>
		/// <param name="fieldName">Name of the field.</param>
		/// <param name="comparisonOperator">The comparison operator.</param>
		/// <param name="value">The value.</param>
		/// <param name="valueType">Type of the value.</param>
		/// <param name="orderByFieldName">Name of the order by field.</param>
		/// <param name="orderByDirection">The order by direction.</param>
		/// <param name="list">The list.</param>
		/// <param name="rowLimit">The row limit.</param>
		/// <param name="viewFieldNames">The view field names.</param>
		/// <returns></returns>
		public static SPListItemCollection GetItems(string fieldName, ComparisonOperator comparisonOperator, object value, CamlValueType valueType, string orderByFieldName, OrderByDirection orderByDirection, SPList list, uint? rowLimit = null, params string[] viewFieldNames)
		{
			CamlQueryBuilder cqb = new CamlQueryBuilder(fieldName, comparisonOperator, value, valueType, orderByFieldName, orderByDirection, viewFieldNames);
			var items = GetItems(cqb, list, rowLimit);
			return items;
		}

		// List Url Overloads

		/// <summary>
		/// Gets the items.
		/// </summary>
		/// <param name="camlQueryBuilder">The caml query builder.</param>
		/// <param name="listUrl">The list URL.</param>
		/// <param name="web">The web.</param>
		/// <param name="rowLimit">The row limit.</param>
		/// <returns></returns>
		public static SPListItemCollection GetItems(CamlQueryBuilder camlQueryBuilder, string listUrl, SPWeb web, uint? rowLimit = null)
		{
			SPListItemCollection items = null;
			CamlQuery camlQuery = new CamlQuery(camlQueryBuilder, rowLimit);
			SPList list = CamlQueryHelper.TryGetListByRelativeUrl(listUrl, web);
			if (list != null)
			{
				items = list.GetItems(camlQuery);
			}
			return items;
		}

		/// <summary>
		/// Gets the items.
		/// </summary>
		/// <param name="fieldId">The field id.</param>
		/// <param name="comparisonOperator">The comparison operator.</param>
		/// <param name="value">The value.</param>
		/// <param name="valueType">Type of the value.</param>
		/// <param name="listUrl">The list URL.</param>
		/// <param name="web">The web.</param>
		/// <param name="rowLimit">The row limit.</param>
		/// <param name="viewFieldIds">The view field ids.</param>
		/// <returns></returns>
		public static SPListItemCollection GetItems(Guid fieldId, ComparisonOperator comparisonOperator, object value, CamlValueType valueType, string listUrl, SPWeb web, uint? rowLimit = null, params Guid[] viewFieldIds)
		{
			CamlQueryBuilder cqb = new CamlQueryBuilder(fieldId, comparisonOperator, value, valueType, viewFieldIds);
			var items = GetItems(cqb, listUrl, web, rowLimit);
			return items;
		}

		/// <summary>
		/// Gets the items.
		/// </summary>
		/// <param name="fieldName">Name of the field.</param>
		/// <param name="comparisonOperator">The comparison operator.</param>
		/// <param name="value">The value.</param>
		/// <param name="valueType">Type of the value.</param>
		/// <param name="listUrl">The list URL.</param>
		/// <param name="web">The web.</param>
		/// <param name="rowLimit">The row limit.</param>
		/// <param name="viewFieldNames">The view field names.</param>
		/// <returns></returns>
		public static SPListItemCollection GetItems(string fieldName, ComparisonOperator comparisonOperator, object value, CamlValueType valueType, string listUrl, SPWeb web, uint? rowLimit = null, params string[] viewFieldNames)
		{
			CamlQueryBuilder cqb = new CamlQueryBuilder(fieldName, comparisonOperator, value, valueType, viewFieldNames);
			var items = GetItems(cqb, listUrl, web, rowLimit);
			return items;
		}

		/// <summary>
		/// Gets the items.
		/// </summary>
		/// <param name="fieldId">The field id.</param>
		/// <param name="comparisonOperator">The comparison operator.</param>
		/// <param name="value">The value.</param>
		/// <param name="valueType">Type of the value.</param>
		/// <param name="orderByFieldId">The order by field id.</param>
		/// <param name="orderByDirection">The order by direction.</param>
		/// <param name="listUrl">The list URL.</param>
		/// <param name="web">The web.</param>
		/// <param name="rowLimit">The row limit.</param>
		/// <param name="viewFieldIds">The view field ids.</param>
		/// <returns></returns>
		public static SPListItemCollection GetItems(Guid fieldId, ComparisonOperator comparisonOperator, object value, CamlValueType valueType, Guid orderByFieldId, OrderByDirection orderByDirection, string listUrl, SPWeb web, uint? rowLimit = null, params Guid[] viewFieldIds)
		{
			CamlQueryBuilder cqb = new CamlQueryBuilder(fieldId, comparisonOperator, value, valueType, orderByFieldId, orderByDirection, viewFieldIds);
			var items = GetItems(cqb, listUrl, web, rowLimit);
			return items;
		}

		/// <summary>
		/// Gets the items.
		/// </summary>
		/// <param name="fieldName">Name of the field.</param>
		/// <param name="comparisonOperator">The comparison operator.</param>
		/// <param name="value">The value.</param>
		/// <param name="valueType">Type of the value.</param>
		/// <param name="orderByFieldName">Name of the order by field.</param>
		/// <param name="orderByDirection">The order by direction.</param>
		/// <param name="listUrl">The list URL.</param>
		/// <param name="web">The web.</param>
		/// <param name="rowLimit">The row limit.</param>
		/// <param name="viewFieldNames">The view field names.</param>
		/// <returns></returns>
		public static SPListItemCollection GetItems(string fieldName, ComparisonOperator comparisonOperator, object value, CamlValueType valueType, string orderByFieldName, OrderByDirection orderByDirection, string listUrl, SPWeb web, uint? rowLimit = null, params string[] viewFieldNames)
		{
			CamlQueryBuilder cqb = new CamlQueryBuilder(fieldName, comparisonOperator, value, valueType, orderByFieldName, orderByDirection, viewFieldNames);
			var items = GetItems(cqb, listUrl, web, rowLimit);
			return items;
		}

		/// <summary>
		/// Tries to get the list that is associated with the specified web-relative URL.
		/// </summary>
		/// <param name="relativeUrl"> A string that contains the web-relative URL for a list, for example, /Lists/Announcements.</param>
		/// <param name="web">The web to get the list from.</param>
		/// <returns>An SPList object. Returns null if the list doesn't exist at the specified URL.</returns>
		private static SPList TryGetListByRelativeUrl(string relativeUrl, SPWeb web)
		{
			SPList list = null;
			try
			{
				relativeUrl = SPUrlUtility.CombineUrl(web.ServerRelativeUrl, relativeUrl);
				list = web.GetList(relativeUrl);
			}
			catch (Exception ex)
			{
				string errorMessage = string.Format("List not found at web '{0}' with url '{1}'.", web.Url, relativeUrl);
				TraceProvider.Log(errorMessage, TraceProviderCategories.Default, (uint)TraceProviderEventIds.CamlQueries, TraceProviderSeverity.Information, ex);
			}
			return list;
		}

	}
}
